#include "SoftTimer.h"


#define MAX_TIMER_NUM 10U

/* ---------------------------------------------*/
/* --------------- Private Types ---------------*/
/* ---------------------------------------------*/
/**@brief List to contain SoftTimer*/
typedef struct {
    SoftTimer_TypeDef* timers[MAX_TIMER_NUM];  /**< container of SoftTimer*/
    uint8_t len;  /**< length of this list*/
} SfTim_Lst;

/* ---------------------------------------------*/
/* -------- Private Global Variables -----------*/
/* ---------------------------------------------*/
SfTim_Lst g_sft_lst;


/* ---------------------------------------------*/
/* ----------- Private Functions ---------------*/
/* ---------------------------------------------*/
static void SfTim_LstInit(void) {
    g_sft_lst.len = 0; 
}

/**@brief Push a SoftTimer into list.
@retval  true success.
@retval false failed.*/
static bool SfTim_LstPush(SoftTimer_TypeDef* sft) {
    // The list is full
    if (g_sft_lst.len >= MAX_TIMER_NUM) {
        return false;
    }
    
    g_sft_lst.timers[g_sft_lst.len] = sft;
    g_sft_lst.len ++;
    
    return true;
}



/* ---------------------------------------------*/
/* ----------- Exported Functions --------------*/
/* ---------------------------------------------*/
/**@brief Init SoftTimer system. This function must be called before use SoftTimer.*/
void SfTim_InitSys(void) {
    SfTim_LstInit();
}


/**@brief Init the SoftTimer object.
@param sft        The SoftTimer object.
@param final_val  The SoftTimer's final_val.
@param cb         The callback function.*/
bool SfTim_Init(SoftTimer_TypeDef *sft, uint32_t final_val, void(*cb)()) {
    sft->cnt = 0;
    sft->final_val = final_val;
    sft->callback = cb;
    sft->enabled = true;
    
    return SfTim_LstPush(sft);
}


void SfTim_Enable(SoftTimer_TypeDef *sft) {
    sft->enabled = true;
}


void SfTim_Disable(SoftTimer_TypeDef *sft) {
    sft->enabled = false;
}


void SfTim_CountAll(void) {
    SoftTimer_TypeDef* _sft;
    
    for (uint8_t i=0; i < g_sft_lst.len; i++) {
        _sft = g_sft_lst.timers[i];
        
        if (_sft->enabled) {
            (_sft->cnt)++;
            
            if ((_sft->cnt) > (_sft->final_val)) {
                _sft->cnt = 0;
                _sft->callback();
            }
        }
    }
    
}
